import math

'''
d=2,fmin=-1.8013
d=5,fmin=-4.687658
d=10 fmin=-9.66015
'''


def range_function(fu):
    if fu == 'Michalewicz':
        return 0,math.pi,0,'Michalewicz'
    elif fu == 'Shubert':
        return -10,10,0,'Shubert'
    elif fu == 'Griewank':
        return -600,600,0,'Griewank'
    elif fu == 'Eggholder':
        return -512,512,0,'Eggholder'
    elif fu == 'Bukin':
        return -5.12,5.12,0,'Bukin'
    elif fu == 'Schwefe':
        return -500,500,0,'Schwefe'
    elif fu == 'Schaffer':
        return -100,100,0,'Schaffer'




def choose(fu, dim, arr):
    if fu == 'Michalewicz':
        return Michalewicz(dim, arr, 10)
    elif fu == 'Shubert':
        return Shubert(dim, arr)
    elif fu == 'Griewank':
        return Griewank(dim, arr)
    elif fu == 'Eggholder':
        return Eggholder(dim, arr)
    elif fu == 'Bukin':
        return Bukin(dim,arr)
    elif fu == 'Schwefe':
        return Schwefe(dim,arr)
    elif fu == 'Schaffer':
        return Schaffer(dim,arr)



def Michalewicz(dim, arr, m):
    fx = 0
    for i in range(dim):
        fx = fx + math.sin(arr[i]) * ((math.sin(((i + 1) * arr[i] ** 2) / math.pi)) ** (2 * m))
    return -fx


def Shubert(dim, arr):  # Shubert函数(-10,10) (-1.42513,-0.80032) (-186.7309)
    sum = 0
    sum1 = 0
    for i in range(1, 6):
        sum = sum + i * math.cos((i + 1) * arr[0] + i)
        sum1 = sum1 + i * math.cos((i + 1) * arr[1] + i)
    s = sum * sum1
    return s


def Griewank(dim, arr):
    fx1 = 0
    fx2 = 1
    for i in range(dim):
        fx1 = fx1 + (arr[i] ** 2) / 4000
        fx2 = fx2*math.cos(arr[i]/math.sqrt(i+1))
    return fx1-fx2+1

def Eggholder(dim, arr):
    fx = -(arr[1]+47)*math.sin(math.sqrt(abs(arr[1]+arr[0]/2+47)))-arr[0]*math.sin(math.sqrt(abs(arr[0]-(arr[1]+47))))
    return fx

def Bukin(dim,arr):
    fx=100*math.sqrt(abs(arr[1]-0.01*arr[0]**2))+0.01*abs(arr[0]+10)
    return fx

def Schwefe(dim,arr):
    fx=418.9829*dim
    for i in range(dim):
        fx=fx-arr[i]*math.sin(math.sqrt(abs(arr[i])))
    return fx
def Schaffer(dim,arr):
    fx=0.5+(math.sin(arr[0]**2-arr[1]**2)**2-0.5)/(1+0.001*(arr[0]**2+arr[1]**2))**2
    return fx